﻿#include "ui_seach.h"
#include "ui_ui_seach.h"
#include "define.h"
#include <QTimer>
#include <QDomDocument>
#include <QtXml>
#include <QList>
#include <QNetworkInterface>
#include <QMessageBox>

#define GW_UDP_PORT          12306    // Gateway 网关UDP端口
#define LC_UDP_PORT          8192     // Local   本地UDP端口
#define UDP_PROTOCOL_VER     "0"      // UDP协议版本号

uiSeach::uiSeach(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::uiSeach)
{
    ui->setupUi(this);

    // 获取ipv4列表
    this->m_entries = new QList<QNetworkAddressEntry>;
    getIpv4(this->m_entries);
    foreach (QNetworkAddressEntry entry, *m_entries) {
        ui->ipBox->addItem(entry.ip().toString());
    }

    // 初始化向量
    this->m_udpInfo = new QVector<udpDeviceInfo_t>;

    // 初始化UDP
    this->m_udp = new QUdpSocket;

    // 绑定
    if (!this->m_udp->bind(LC_UDP_PORT))
    {
        qDebug() << "UDP 套接字创建失败！";
    }

    // 准备接收数据
    connect(m_udp, &QUdpSocket::readyRead, this, &uiSeach::udpReadData);

    // 连接发送广播槽函数
    connect(this, &uiSeach::startSearch, this, &uiSeach::sendBroad);

    // 表格点击槽
    connect(ui->devTable, &QTableWidget::cellClicked, this, &uiSeach::showDevInfo);

//    emit startSearch();
}

uiSeach::~uiSeach()
{
    delete ui;
    delete this->m_entries;
}

void uiSeach::getIpv4(QList<QNetworkAddressEntry> * entries)
{
    QList<QNetworkInterface>list = QNetworkInterface::allInterfaces();
    foreach (QNetworkInterface interface, list)
    {
        QList<QNetworkAddressEntry> entriesList = interface.addressEntries();
        foreach (QNetworkAddressEntry entry, entriesList)
        {
            if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol)
            {
                entries->append(entry);
                qDebug() << "ip: " << entry.ip().toString();
                qDebug() << "broadcase: " << entry.broadcast().toString();
            }
        }
    }
}

bool uiSeach::isValidIPAddress(const QString &ip)
{
    QRegExp ipReg("^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$");
    return ipReg.exactMatch(ip);
}

void uiSeach::closeEvent(QCloseEvent *event)
{
    {
        // 在这里处理关闭事件，例如保存数据等
        qDebug() << "关闭UDP套接字...";
        this->m_udp->close();
        this->m_udp->deleteLater();

        // 调用基类的closeEvent()函数，以确保析构函数被调用
        QWidget::closeEvent(event);
    }
}

void uiSeach::udpReadData()
{
    qint64 len = m_udp->pendingDatagramSize();
    if (len > 0)
    {
        QByteArray datagram;
        datagram.resize(len);
        m_udp->readDatagram(datagram.data(), datagram.size());
        xmlRead(datagram);
    }
}

void uiSeach::sendBroad()
{
    qDebug() << "开始搜索簇控制器";

    ui->search->setEnabled(false);
    ui->search->setText("搜索中...");

    this->m_udpInfo->clear(); // 清空UDP设备向量
    ui->devTable->setRowCount(0);

    QByteArray tBfu = QByteArray::fromStdString(this->xmlSearch().toStdString());
    QHostAddress curBroadcase = m_entries->at(ui->ipBox->currentIndex()).broadcast();
    if (curBroadcase.toString() == "")
    {
        QMessageBox::warning(this, "搜索失败", "此网络地址无效！");
        ui->search->setEnabled(true);
        ui->search->setText("重新搜索");
        return;
    }
    else
    {
        m_udp->writeDatagram(tBfu, curBroadcase, GW_UDP_PORT);
    }


    QTimer::singleShot(500, this, [=](){
        ui->search->setEnabled(true);
        ui->search->setText("重新搜索");

        if (this->m_udpInfo->size() == 0)
        {
            QMessageBox::information(this, "搜索失败", "未找到簇控制器，请检查设备的连接状态！");
            return;
        }
        else
        {
            ui->devTable->setRowCount(m_udpInfo->size());
            QTableWidgetItem * item = nullptr;
            for(int i = 0; i < m_udpInfo->size(); i++)
            {
                item = new QTableWidgetItem;
                item->setText(m_udpInfo->at(i).sn);
                item->setTextAlignment(Qt::AlignCenter);
                ui->devTable->setItem(i, 0, item);

                item = new QTableWidgetItem;
                item->setText(m_udpInfo->at(i).mac);
                item->setTextAlignment(Qt::AlignCenter);
                ui->devTable->setItem(i, 1, item);

                item = new QTableWidgetItem;
                item->setText(m_udpInfo->at(i).ip);
                item->setTextAlignment(Qt::AlignCenter);
                ui->devTable->setItem(i, 2, item);
            }
        }
    });
}

void uiSeach::on_search_clicked()
{
    emit startSearch();
}

void uiSeach::on_connectCluster_clicked()
{
    if (!this->isValidIPAddress(ui->ip->text()))
    {
        QMessageBox::warning(this, "连接失败", "请选择需要连接的设备");
        return;
    }
    else
    {
        emit clusterConnect(m_udpInfo->at(m_curDevIndex));
        this->close();
        this->deleteLater();
    }
}

void uiSeach::showDevInfo(int row, int column)
{
    qDebug() << QString("Table Clicked! row: %1, column: %2").arg(row).arg(column);
    // 在设备列表中查找设备
    QString devSn = ui->devTable->item(row, 0)->text();
    int devIndex = -1;
    for(int i = 0; i < m_udpInfo->size(); i++)
    {
        if (devSn == m_udpInfo->at(i).sn)
        {
            devIndex = i;
        }
    }
    if (devIndex == -1)
    {
        qDebug() << "列表中未找到该设备！";
        return;
    }
    else
    {
        m_curDevIndex = devIndex;
        ui->modle->setText(m_udpInfo->at(devIndex).model);
        ui->sn->setText(m_udpInfo->at(devIndex).sn);
        ui->ip->setText(m_udpInfo->at(devIndex).ip);
        ui->mac->setText(m_udpInfo->at(devIndex).mac);
        ui->ver->setText(m_udpInfo->at(devIndex).ver);
        ui->gw->setText(m_udpInfo->at(devIndex).gw);
        ui->mask->setText(m_udpInfo->at(devIndex).mask);
        ui->dns1->setText(m_udpInfo->at(devIndex).dns1);
        ui->dns2->setText(m_udpInfo->at(devIndex).dns2);
        ui->dhcp->setText(m_udpInfo->at(devIndex).dhcp ? g_dhcp[0] : g_dhcp[1]);
    }
}

QString uiSeach::xmlSearch()
{
    // xml文件
    QDomDocument doc;

    // xml描述
    QDomProcessingInstruction head =
            doc.createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\"");
    doc.appendChild(head);

    // 根节点
    QDomElement tree = doc.createElement("SEARCH_GW_REQ");
    doc.appendChild(tree);

    // ver
    QDomElement ver = doc.createElement("ver");
    QDomText verText = doc.createTextNode(UDP_PROTOCOL_VER);
    ver.appendChild(verText);
    tree.appendChild(ver);

    // ip
    QString ipAddr = ui->ipBox->currentText();
    QDomElement ip = doc.createElement("ip");
    QDomText ipText = doc.createTextNode(ipAddr);
    ip.appendChild(ipText);
    tree.appendChild(ip);

    // port
    QDomElement port = doc.createElement("port");
    QDomText portText = doc.createTextNode(QString("%1").arg(LC_UDP_PORT));
    port.appendChild(portText);
    tree.appendChild(port);

    return doc.toString();
}

void uiSeach::xmlRead(QString tree)
{
    QDomDocument doc;
    udpDeviceInfo_t dev;

    // 加载xml
    if(!doc.setContent(tree))
    {
        qDebug() << "xml加载失败！";
        return;
    }

    //返回根节点
    QDomElement root = doc.documentElement();

    //获得第一个子节点
    QDomNode node = root.firstChild();
    while(!node.isNull())  // 如果节点不空
    {
        if(node.isElement()) // 如果节点是元素
        {
            QDomElement e = node.toElement(); // 转换为元素，注意元素和节点是两个数据结构，其实差不多
            if (e.tagName() == "id")
            {
                dev.sn = e.text();
            }
            else if (e.tagName() == "sn")
            {
                dev.sn = e.text();
            }
            else if (e.tagName() == "ip")
            {
                dev.ip = e.text();
            }
            else if (e.tagName() == "mac")
            {
                dev.mac = e.text();
            }
            else if (e.tagName() == "ver")
            {
                dev.ver = e.text();
            }
            else if (e.tagName() == "net")
            {
                if (e.text() == "1")
                {
                    dev.dhcp = true;
                }
                else
                {
                    dev.dhcp = false;
                }
            }
            else if (e.tagName() == "netmask")
            {
                dev.mask = e.text();
            }
            else if (e.tagName() == "gateway")
            {
                dev.gw = e.text();
            }
            else if (e.tagName() == "dns0")
            {
                dev.dns1 = e.text();
            }
            else if (e.tagName() == "dns1")
            {
                dev.dns2 = e.text();
            }
            else if (e.tagName() == "model")
            {
                dev.model = e.text();
            }
        }
        node = node.nextSibling(); // 下一个兄弟节点,nextSiblingElement()是下一个兄弟元素，都差不多
    }

    this->udpInfoAdd(dev);
}

bool uiSeach::udpInfoAdd(udpDeviceInfo_t &dev)
{
    for (int i = 0; i < this->m_udpInfo->size(); i++)
    {
        if (this->m_udpInfo->at(i).sn == dev.sn)
        {
            return false;
        }
    }

    this->m_udpInfo->append(dev);
    return true;
}
